import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import BinaryOperators.*;


public class Interpeter {
	final static int PRECISION_DEGREE = 5;
	final static String OVERLOAD_CMD = "overload";
	
	// Data Members:
	//map includes binary operators: 
	private static Map<String,BinaryOperator> _binaryOpMap = new HashMap<String,BinaryOperator>();
	private static Map<String,AssignmentOperator> _assignOpMap = new HashMap<String,AssignmentOperator>();
	private static Map<String,Variable> _variableMap = new HashMap<String,Variable>();
	private static Map<String,Function> _functionsMap = new HashMap<String,Function>();


	public static void main(String[] args) {
		InitializeOpMap();
		InitializeAssignMap();
		InitializFuncMap();
		Scanner scan = new Scanner(System.in);
		String s = scan.nextLine();
		s.trim();
		while (!s.equals("out")) {
			if(isOverloadCommand(s)){
				if(isOverLoadLegal(s)){
					overload(s);
				}else{
					//TODO add exception.
				}
			}else{
				
			PrintResult(Interpret(s));
			}
			s = scan.nextLine();
		}
	}


	private static void overload(String s) {
		String overloadStucture = "(overload)(\\s*)([^\\w\\s\\(\\)\\[\\]\\{\\}]{1,2})(\\s)(MOD|POW)";
		Pattern pat = Pattern.compile(overloadStucture);
		Matcher matcher = pat.matcher(s);
		matcher.find();
		_binaryOpMap.put
		(matcher.group(3), new OverloadedOperator(_functionsMap.get(matcher.group(5))));
	}


	private static void PrintResult(double a) {
		System.out.printf("%." + PRECISION_DEGREE + "f", a);
		System.out.println();
	}

	private static boolean IsAssignmentLegal(String line){
		String[] assignmentComponents = line.split(" ");
		//verifying the assignment line begins with the variable's name:
		if(!isLegalVariablName(assignmentComponents[0])){
			System.out.println("illegal variable name");
			return false;
		}
		//Verifying there is only one assignment in the line:
		String assignOperators = "=";//|\\+=|-=|\\*=|/=";
		Pattern pat = Pattern.compile(assignOperators);
		Matcher matcher = pat.matcher(line);
		matcher.find();
		if (isAssignmentEquation(line.substring(matcher.start()+1))){
			System.out.println("Error: more then one assignment per line");
			return false; 
		}
		if(!assignmentComponents[1].equals("=")&&!_variableMap.containsKey(assignmentComponents[0])){
			//TODO add exception here:
			System.out.println("Error: variable wasn't initialized");
		}
		
		
		
		return true;
	}
	
	
	
	
	
	private static double Interpret(String s) {
		List<EquationComponent> _lineComponents = new ArrayList<EquationComponent>();
		
		//checking whether it's an assignment equation:
		if(isAssignmentEquation(s)){
			//verifying assignment is legal:
			if(IsAssignmentLegal(s)){
				String temp = s.substring(0, s.indexOf("=")+2);
				s = temp.concat(Double.toString((Interpret(s.substring(s.indexOf("=")+1).trim()))));
				
			}else{
				//TODO add exception
			}
		}
		
		
		//handling brackets:
		s = CalcBrackets(s);
		//handling functions:
		s = CalcFunctions(s);
		
		
		String[] StringComponents = s.split(" ");
		double result = 0;
		double tempResult;
		for (int i = 0; i < StringComponents.length; i++) {
			_lineComponents.add(InterpretComponent(StringComponents[i]));
		}

		//if the current line component is a binary operator, then it's result
		//is calculated, and is assigned instead of the operator and it's arguments: 
		for(int i=0; i<_lineComponents.size();i++){
			
			if (_lineComponents.get(i) instanceof BinaryOperator){
				double opertorResult = _lineComponents.get(i).Execute(
						_lineComponents.get(i-1).Execute(null),
						_lineComponents.get(i+1).Execute(null));
				Number resultNumber = new Number(opertorResult);
				_lineComponents.set(i+1, resultNumber);
		}else if(_lineComponents.get(i) instanceof AssignmentOperator){
			tempResult = _lineComponents.get(i).Execute(_lineComponents.get(i-1).Execute(null),
					_lineComponents.get(i+1).Execute(null));
			((Variable)_lineComponents.get(i-1)).updateValue(tempResult);
			_lineComponents.set(i+1,_lineComponents.get(i-1));
		}
			
			
			

		}
		result = _lineComponents.get(_lineComponents.size() - 1).Execute();
		return result;
	}

	//interprets the component and returns it as equation object (Number, Operator, Variable):
	private static EquationComponent InterpretComponent(String str){
		//checking if it's a number:
		if(isLegalNumber(str)){
			return new Number(Double.parseDouble(str));
		//checking if it's an existing variable:
		}else if(_variableMap.containsKey(str)){
			return  _variableMap.get(str);
		//checking if ir's a new variable:
		}else if(isLegalVariablName(str)){
			Variable newVar = new Variable(str,0);
			_variableMap.put(str, newVar);
			return newVar;
		//checking if it's an operator:
		}else if(_binaryOpMap.containsKey(str)){
			return _binaryOpMap.get(str);
		//checking if it's an assignment operator:
		}else if(_assignOpMap.containsKey(str)){
			return	_assignOpMap.get(str);
		}
		//else, it's an invalid expression, an exception is thrown:
		//TODO add exception here: 
		return null;
	}
	
	
	
	
	// a private method that finds brackets (if they exist), calculates their
	// content,
	// and returns their content value.
	private static String CalcBrackets(String s) {
		// searching for brackets in the line:
		String patText = "(\\[)(.*)(\\])";
		Pattern pat = Pattern.compile(patText);
		Matcher matcher = pat.matcher(s);
		// if brackets were found, they are calculated and they are replaced in
		// the string with their result:
		if (matcher.find()) {
			return s.replaceAll(patText,new Double
					(Interpret(s.substring(matcher.start() + 1,matcher.end() - 1))).toString());
		} else {
			return s;
		}
	}
	
	
	private static String CalcFunctions(String str){
		String legalNumber = "MAX|MIN|MOD|POW|ABS|EXP|LOG";
		Pattern pat = Pattern.compile(legalNumber);
		Matcher matcher = pat.matcher(str);
		if (matcher.find()){
			double[] args = returnArgsForFunction(str);
			return str.replace(str.substring(matcher.start(), str.lastIndexOf("}")+1), 
//			return str.replace(str.substring(matcher.start(), str.indexOf("}")+1), 
					new Double (_functionsMap.get(str.substring
							(matcher.start(), matcher.end())).Execute(args)).toString());

		}
		return str;
	}
	
	
	private static double[] returnArgsForFunction(String str){
		String patText = "(\\{)(.*)(\\})";
		Pattern pat = Pattern.compile(patText);
		Matcher matcher = pat.matcher(str);
		
		
		if(matcher.find()){
			String temp = str.substring(matcher.start()+1, matcher.end()-1);
			String[] args = temp.split(",");
			double[] argsInDouble = new double[args.length];
			for(int i=0; i<args.length; i++){
				argsInDouble[i] = Interpret((args[i].trim()));
			}
			return argsInDouble;
		}else{
			//else there are no parentheses, an error
			//TODO: handle error:
			throw new IndexOutOfBoundsException();
		}

	}
	
	//returns true if the line is an overload command, false otherwise:
	private static boolean isOverloadCommand(String str){
		if(str.startsWith(OVERLOAD_CMD)){
			return true;
		}else{
			return false;
		}
	}
	
	//returns true if the overload command is legal, i.e. if the new op name is legal, 
	//and the function selected is one of the two binary functions.
	//returns false otherwise.
	private static boolean isOverLoadLegal(String s) {
		String overloadStucture = "(overload)(\\s*)([^\\w\\s\\(\\)\\[\\]\\{\\}]{1,2})(\\s)(MOD|POW)";
		Pattern pat = Pattern.compile(overloadStucture);
		Matcher matcher = pat.matcher(s);
		if(matcher.find()){
			return true;
		}else{
			return false;
		}
	}
	
	private static boolean isLegalNumber(String str){
		String legalNumber = "^\\d+\\.?\\d+$|^\\d*$";
		Pattern pat = Pattern.compile(legalNumber);
		Matcher matcher = pat.matcher(str);
		if (matcher.find()) {
			return true;
		}else{
			return false;
		}
	}
	
	
	private static boolean isLegalVariablName(String str){
		String varLegalName = "@[a-z][a-z0-9]*[0-9]$";
		Pattern pat = Pattern.compile(varLegalName);
		Matcher matcher = pat.matcher(str);
		if (matcher.find()){
			return true;
		}else{
			return false;
		}
	}
	
	private static boolean isAssignmentEquation(String str){
		String assignOperators = "=|\\+=|-=|\\*=|/=";
		Pattern pat = Pattern.compile(assignOperators);
		Matcher matcher = pat.matcher(str);
		if (matcher.find()){
			return true;
		}else{
			return false;
		}
	}
	
	
	private static void InitializeOpMap(){
		_binaryOpMap.put("+", new Plus());
		_binaryOpMap.put("-", new Minus());
		_binaryOpMap.put("*", new Times());
		_binaryOpMap.put("/", new Divide());
	}
	
	private static void InitializeAssignMap(){
		_assignOpMap.put("=", new Assign());
		_assignOpMap.put("+=", new AddAssign());
		_assignOpMap.put("-=", new SubtractAssign());
		_assignOpMap.put("*=", new MultiAssign());
		_assignOpMap.put("/=", new DivAssign());
		
	}
	
	private static void InitializFuncMap(){
		_functionsMap.put("MAX", new MaxFunction());
		_functionsMap.put("MIN", new MinFunction());
		_functionsMap.put("MOD", new ModFunction());
		_functionsMap.put("POW", new PowFunction());
		_functionsMap.put("ABS", new AbsFunction());
		_functionsMap.put("EXP", new ExpFunction());
		_functionsMap.put("LOG", new LogFunction());
	}
	
	
}
